package com.jx.driving.protocol.terminal.codec;

import java.io.ByteArrayOutputStream;
import java.nio.ByteBuffer;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.jx.driving.message.Message;

/**
 * 终端协议,head解码
 * 
 * @author shenliuyang
 *
 *         2016年8月4日下午2:11:07
 */
public class TerminalHeadCodec implements Codec {

	private Logger logger = LoggerFactory.getLogger(TerminalHeadCodec.class);

	@Override
	public Object decode(com.jx.driving.protocol.terminal.channel.Channel c, Object in) {
		if (!(in instanceof byte[])) {
			return in;
		}
		byte[] content = (byte[]) in;
		Message msg = byteBufferToMessage(ByteBuffer.wrap(content));
		logger.info("request|{}|{}", msg.getMessageHeader().getPhone(), byteArrayToHexString(content));
		return msg;
	}

	@Override
	public Object encode(com.jx.driving.protocol.terminal.channel.Channel c, Object in) {
		if (!(in instanceof Message)) {
			return in;
		}
		Message msg = (Message) in;
		byte[] data = msg.getMessageByteArray();
		logger.info("response|{}|{}", msg.getMessageHeader().getPhone(), byteArrayToHexString(data));
		ByteArrayOutputStream o = new ByteArrayOutputStream(data.length * 2);
		o.write(data[0]);
		// 头尾不转译
		for (int i = 1; i < data.length - 1; i++) {
			if (data[i] == 0x7e) {
				o.write(0x7d);
				o.write(0x02);
				continue;
			}
			o.write(data[i]);
			if (data[i] == 0x7d) {
				o.write(0x01);
			}

		}
		o.write(data[data.length - 1]);
		return o.toByteArray();
	}

	protected Message byteBufferToMessage(ByteBuffer buffer) {
		ByteBuffer escapeBuf = ByteBuffer.allocate(buffer.remaining());
		escapeBuf.put(buffer.get());// 第一位不转码
		while (buffer.remaining() > 1) {
			byte b = buffer.get();
			if (b != 0x7d) {
				escapeBuf.put(b);
				continue;
			}
			// 获取第二位,确定第一位的值
			byte suffix = buffer.get();
			if (suffix == 0x02) {
				escapeBuf.put((byte) 0x7e);
			} else if (suffix == 0x01) {
				escapeBuf.put((byte) 0x7d);
			} else {
				buffer.position(0);
				byte[] data = new byte[buffer.remaining()];
				buffer.get(data);
				logger.error("not valid codec byte array {}", data);
				return null;
			}
		}
		escapeBuf.put(buffer.get());// 最后一位不转码
		escapeBuf.flip();
		byte[] data = new byte[escapeBuf.remaining()];
		escapeBuf.get(data);
		int len = data.length - 2;
		byte checkCode = (byte) (data[1] ^ data[2]);
		for (int i = 3; i < len; i++) {
			checkCode ^= data[i];
		}
		if (checkCode != data[len]) {
			logger.warn("client checkcode {}  calculated checkcode is {}", Integer.toHexString(data[len] & 0xFF),
					Integer.toHexString(checkCode & 0xFF));
		}
		escapeBuf.clear();
		return new Message(data);
	}

	protected static String byteArrayToHexString(byte[] content) {
		StringBuilder sb = new StringBuilder();
		for (byte b : content) {
			sb.append(String.format("%02X ", b).trim());
		}
		return sb.toString().toUpperCase();
	}
}
